package rollercoaster.commons;

import java.util.ArrayList;

import rollercoaster.commons.interfaces.Surface3D;
import rollercoaster.commons.interfaces.SurfaceTessellationAlgorithm;
import rollercoaster.commons.interfaces.TextureCoordinateEvaluator;
import rollercoaster.environment.interfaces.IModelReader;
import rollercoaster.environment.utils.ObjFace;

public class FixedStepTessellation implements SurfaceTessellationAlgorithm{

	private float step_u;
	private float step_v;
	private TextureCoordinateEvaluator textureCoordinateEvaluator;

	public FixedStepTessellation(TextureCoordinateEvaluator textureCoordinateEvaluator) {
		super();
		this.textureCoordinateEvaluator=textureCoordinateEvaluator;
	}

	public void setStep_u(float step_u) {
		this.step_u = step_u;
	}

	public void setStep_v(float step_v) {
		this.step_v = step_v;
	}

	public IModelReader tessellate(Surface3D surface) {
		DataModel model=new DataModel();
		ArrayList<Vertex3D> vertices=new ArrayList<Vertex3D>();
		ArrayList<Vertex3D> normals=new ArrayList<Vertex3D>();
		ArrayList<Vertex2D> textureCoordinates=new ArrayList<Vertex2D>();
		ArrayList<ObjFace> faces=new ArrayList<ObjFace>();
		
		//DataModel and lists initialization...
		int divisions_u=(int) ((surface.getEndUPoint()-surface.getStartUPoint())/step_u);
		int divisions_v=(int) ((surface.getEndVPoint()-surface.getStartVPoint())/step_v);
		float stepu=(surface.getEndUPoint()-surface.getStartUPoint())/divisions_u;
		float stepv=(surface.getEndVPoint()-surface.getStartVPoint())/divisions_v;
		
		for (int i = 0; i < divisions_v; i++) {
			float v=surface.getStartVPoint()+stepv*i;
			float v1=v+stepv;
			
			for (int j = 0; j <= divisions_u; j++) {
				float u=surface.getStartUPoint()+stepu*j;
				vertices.add(surface.sigma(u, v));
				normals.add(surface.getNormal(u, v));
				textureCoordinates.add(textureCoordinateEvaluator.evaluateTextureCoordinates(surface, u, v));
				vertices.add(surface.sigma(u, v1));
				normals.add(surface.getNormal(u, v1));
				textureCoordinates.add(textureCoordinateEvaluator.evaluateTextureCoordinates(surface, u, v1));
				if(j!=0){
					int size= vertices.size();
					int[] vert={size-3,size-2,size-1};
					int[] vert1={size-2, size-1,size};
					faces.add(new ObjFace(vert, vert, vert));
					faces.add(new ObjFace(vert1, vert1, vert1));
				}
			}
		}
		model.setVertices(vertices);
		model.setNormals(normals);
		model.setTextCoord(textureCoordinates);
		model.setFaces(faces);
		return model;
	}
	
}